package org.jivesoftware.smack;

import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.Presence.Type;
import org.jivesoftware.smack.packet.XMPPError;
import org.jivesoftware.smack.packet.XMPPError.Condition;
import org.jivesoftware.smack.sasl.SASLMechanism.Challenge;
import org.jivesoftware.smack.sasl.SASLMechanism.Success;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

class PacketReader
{
  private XMPPConnection connection;
  private String connectionID = null;
  private Semaphore connectionSemaphore;
  private boolean done;
  private ExecutorService listenerExecutor;
  private XmlPullParser parser;
  private Thread readerThread;

  protected PacketReader(XMPPConnection paramXMPPConnection)
  {
    this.connection = paramXMPPConnection;
    init();
  }

  private void parseFeatures(XmlPullParser paramXmlPullParser)
    throws Exception
  {
    int i = 0;
    boolean bool = false;
    int j = 0;
    while (true)
    {
      do
        while (true)
        {
          while (true)
          {
            int k;
            label342: 
            do
              while (true)
              {
                do
                  while (true)
                  {
                    while (true)
                    {
                      while (true)
                      {
                        while (true)
                        {
                          while (true)
                          {
                            while (true)
                            {
                              while (true)
                              {
                                if (j != 0)
                                {
                                  if ((this.connection.isSecureConnection()) || (i != 0) || (this.connection.getConfiguration().getSecurityMode() != ConnectionConfiguration.SecurityMode.required))
                                    break label416;
                                  throw new XMPPException("Server does not support security (TLS), but security required by connection configuration.", new XMPPError(XMPPError.Condition.forbidden));
                                }
                                k = paramXmlPullParser.next();
                                if (k != 2)
                                  break label342;
                                if (!(paramXmlPullParser.getName().equals("starttls")))
                                  break;
                                i = 1;
                              }
                              if (!(paramXmlPullParser.getName().equals("mechanisms")))
                                break;
                              this.connection.getSASLAuthentication().setAvailableSASLMethods(PacketParserUtils.parseMechanisms(paramXmlPullParser));
                            }
                            if (!(paramXmlPullParser.getName().equals("bind")))
                              break;
                            this.connection.getSASLAuthentication().bindingRequired();
                          }
                          if (!(paramXmlPullParser.getName().equals("ver")))
                            break;
                          this.connection.getConfiguration().setRosterVersioningAvailable(true);
                        }
                        if (!(paramXmlPullParser.getName().equals("c")))
                          break;
                        String str1 = paramXmlPullParser.getAttributeValue(null, "node");
                        String str2 = paramXmlPullParser.getAttributeValue(null, "ver");
                        String str3 = str1 + "#" + str2;
                        this.connection.getConfiguration().setCapsNode(str3);
                      }
                      if (!(paramXmlPullParser.getName().equals("session")))
                        break;
                      this.connection.getSASLAuthentication().sessionsSupported();
                    }
                    if (!(paramXmlPullParser.getName().equals("compression")))
                      break;
                    this.connection.setAvailableCompressionMethods(PacketParserUtils.parseCompressionMethods(paramXmlPullParser));
                  }
                while (!(paramXmlPullParser.getName().equals("register")));
                this.connection.getAccountManager().setSupportsAccountCreation(true);
              }
            while (k != 3);
            if (!(paramXmlPullParser.getName().equals("starttls")))
              break;
            this.connection.startTLSReceived(bool);
          }
          if ((!(paramXmlPullParser.getName().equals("required"))) || (i == 0))
            break;
          bool = true;
        }
      while (!(paramXmlPullParser.getName().equals("features")));
      j = 1;
    }
    if ((i == 0) || (this.connection.getConfiguration().getSecurityMode() == ConnectionConfiguration.SecurityMode.disabled))
      label416: releaseConnectionIDLock();
  }

  private void parsePackets(Thread paramThread)
  {
    int i;
    try
    {
      i = this.parser.getEventType();
      do
      {
        if (i != 2)
          break label663;
        if (!(this.parser.getName().equals("message")))
          break label76;
        processPacket(PacketParserUtils.parseMessage(this.parser));
        i = this.parser.next();
        if ((this.done) || (i == 1))
          break label695;
      }
      while (paramThread == this.readerThread);
      break label695:
      label663: label695: label696: label319: label76: label509: if (this.parser.getName().equals("iq"))
        processPacket(PacketParserUtils.parseIQ(this.parser, this.connection));
    }
    catch (Exception localException)
    {
      do
      {
        while (true)
        {
          if (this.done)
            break label695;
          notifyConnectionError(localException);
          break label695:
          if (!(this.parser.getName().equals("presence")))
            break;
          processPacket(PacketParserUtils.parsePresence(this.parser));
        }
        if (!(this.parser.getName().equals("stream")))
          break label319;
      }
      while (!("jabber:client".equals(this.parser.getNamespace(null))));
      int j = 0;
      while (true)
      {
        while (true)
        {
          do
            while (true)
            {
              do
                while (true)
                {
                  while (true)
                  {
                    while (true)
                    {
                      while (true)
                      {
                        while (true)
                        {
                          while (true)
                          {
                            if (j >= this.parser.getAttributeCount());
                            if (this.parser.getAttributeName(j).equals("id"))
                            {
                              this.connectionID = this.parser.getAttributeValue(j);
                              if ("1.0".equals(this.parser.getAttributeValue("", "version")))
                                break label696;
                              releaseConnectionIDLock();
                              break label696:
                            }
                            if (!(this.parser.getAttributeName(j).equals("from")))
                              break label696;
                            this.connection.config.setServiceName(this.parser.getAttributeValue(j));
                            break label696:
                            if (this.parser.getName().equals("error"))
                              throw new XMPPException(PacketParserUtils.parseStreamError(this.parser));
                            if (!(this.parser.getName().equals("features")))
                              break;
                            parseFeatures(this.parser);
                          }
                          if (!(this.parser.getName().equals("proceed")))
                            break;
                          this.connection.proceedTLSReceived();
                          resetParser();
                        }
                        if (!(this.parser.getName().equals("failure")))
                          break label509;
                        String str2 = this.parser.getNamespace(null);
                        if ("urn:ietf:params:xml:ns:xmpp-tls".equals(str2))
                          throw new Exception("TLS negotiation has failed");
                        if (!("http://jabber.org/protocol/compress".equals(str2)))
                          break;
                        this.connection.streamCompressionDenied();
                      }
                      processPacket(PacketParserUtils.parseSASLFailure(this.parser));
                      this.connection.getSASLAuthentication().authenticationFailed();
                    }
                    if (!(this.parser.getName().equals("challenge")))
                      break;
                    String str1 = this.parser.nextText();
                    processPacket(new SASLMechanism.Challenge(str1));
                    this.connection.getSASLAuthentication().challengeReceived(str1);
                  }
                  if (!(this.parser.getName().equals("success")))
                    break;
                  processPacket(new SASLMechanism.Success(this.parser.nextText()));
                  this.connection.packetWriter.openStream();
                  resetParser();
                  this.connection.getSASLAuthentication().authenticated();
                }
              while (!(this.parser.getName().equals("compressed")));
              this.connection.startStreamCompression();
              resetParser();
            }
          while ((i != 3) || (!(this.parser.getName().equals("stream"))));
          this.connection.disconnect();
        }
        return;
        ++j;
      }
    }
  }

  private void processPacket(Packet paramPacket)
  {
    if (paramPacket == null)
      return;
    Iterator localIterator = this.connection.getPacketCollectors().iterator();
    while (true)
    {
      while (!(localIterator.hasNext()))
        this.listenerExecutor.submit(new ListenerNotification(this, paramPacket));
      ((PacketCollector)localIterator.next()).processPacket(paramPacket);
    }
  }

  private void releaseConnectionIDLock()
  {
    this.connectionSemaphore.release();
  }

  private void resetParser()
  {
    try
    {
      this.parser = XmlPullParserFactory.newInstance().newPullParser();
      this.parser.setFeature("http://xmlpull.org/v1/doc/features.html#process-namespaces", true);
      this.parser.setInput(this.connection.reader);
      return;
    }
    catch (XmlPullParserException localXmlPullParserException)
    {
      localXmlPullParserException.printStackTrace();
    }
  }

  void cleanup()
  {
    this.connection.recvListeners.clear();
    this.connection.collectors.clear();
  }

  protected void init()
  {
    this.done = false;
    this.connectionID = null;
    this.readerThread = new Thread(this)
    {
      public void run()
      {
        PacketReader.access$1(this.this$0, this);
      }
    };
    this.readerThread.setName("Smack Packet Reader (" + this.connection.connectionCounterValue + ")");
    this.readerThread.setDaemon(true);
    this.listenerExecutor = Executors.newSingleThreadExecutor(new ThreadFactory(this)
    {
      public Thread newThread()
      {
        Thread localThread = new Thread(paramRunnable, "Smack Listener Processor (" + PacketReader.access$0(this.this$0).connectionCounterValue + ")");
        localThread.setDaemon(true);
        return localThread;
      }
    });
    resetParser();
  }

  void notifyConnectionError(Exception paramException)
  {
    this.done = true;
    this.connection.shutdown(new Presence(Presence.Type.unavailable));
    paramException.printStackTrace();
    Iterator localIterator = this.connection.getConnectionListeners().iterator();
    if (!(localIterator.hasNext()))
      return;
    ConnectionListener localConnectionListener = (ConnectionListener)localIterator.next();
    try
    {
      localConnectionListener.connectionClosedOnError(paramException);
    }
    catch (Exception localException)
    {
      localException.printStackTrace();
    }
  }

  protected void notifyReconnection()
  {
    Iterator localIterator = this.connection.getConnectionListeners().iterator();
    if (!(localIterator.hasNext()))
      return;
    ConnectionListener localConnectionListener = (ConnectionListener)localIterator.next();
    try
    {
      localConnectionListener.reconnectionSuccessful();
    }
    catch (Exception localException)
    {
      localException.printStackTrace();
    }
  }

  public void shutdown()
  {
    Iterator localIterator;
    if (!(this.done))
    {
      localIterator = this.connection.getConnectionListeners().iterator();
      if (localIterator.hasNext())
        break label44;
    }
    this.done = true;
    this.listenerExecutor.shutdown();
    return;
    label44: ConnectionListener localConnectionListener = (ConnectionListener)localIterator.next();
    try
    {
      localConnectionListener.connectionClosed();
    }
    catch (Exception localException)
    {
      localException.printStackTrace();
    }
  }

  public void startup()
    throws XMPPException
  {
    this.connectionSemaphore = new Semaphore(1);
    this.readerThread.start();
    try
    {
      this.connectionSemaphore.acquire();
      int i = SmackConfiguration.getPacketReplyTimeout();
      this.connectionSemaphore.tryAcquire(i * 3, TimeUnit.MILLISECONDS);
      if (this.connectionID == null)
        throw new XMPPException("Connection failed. No response from server.");
      this.connection.connectionID = this.connectionID;
      return;
    }
    catch (InterruptedException localInterruptedException)
    {
    }
  }

  private class ListenerNotification
  implements Runnable
  {
    private Packet packet;

    public ListenerNotification(, Packet paramPacket)
    {
      this.packet = paramPacket;
    }

    public void run()
    {
      Iterator localIterator = PacketReader.access$0(this.this$0).recvListeners.values().iterator();
      while (true)
      {
        if (!(localIterator.hasNext()))
          return;
        ((Connection.ListenerWrapper)localIterator.next()).notifyListener(this.packet);
      }
    }
  }
}